#if PF_TO_NET

#include "PfSocket.h"
#include "Shell.h"
#include "Printf.h"

static PfSocket g_PfSocket;

#define MAX_PF_RESEND_COUNT 3
void PfSocket_task(void * pArg)
{
	int nCount = 0;
	PfSocket* pPfSocket = (PfSocket*)pArg;
	uint32 hSocket;
	int i = 0;
	int nTxLen = 0;
    struct sockaddr_in  server, client;   
	char	revBuf[64] = {0};
	uint32 ipAddr = inet_addr(pPfSocket->m_IpAddr);
	int32 socketAddrLen = sizeof(struct sockaddr_in);
	uint16 nTxPort = htons(pPfSocket->m_TxPort);

	server.sin_family       = AF_INET;                                                           
	server.sin_addr.s_addr  = htonl( INADDR_ANY );   
    server.sin_port         = htons(pPfSocket->m_RxPort);              
   
    hSocket = socket( AF_INET, SOCK_DGRAM, 0 );                          
    if(INVALID_SOCKET == hSocket)
    {
		PF(DL_WARNING, ("PfSocket create failed, port=%d.\n", pPfSocket->m_RxPort));
		return;
    }
	else
	{
		i = bind(hSocket, (struct sockaddr *)&server, sizeof( server ));
	    if(0 != i)
	    {
			PF(DL_WARNING, ("PfSocket bind failed, port=%d, ret=%d.\n", pPfSocket->m_RxPort, i));
			return;
	    }
	}
    //bind(hSocket, (struct sockaddr *)&server, sizeof( server ));       
	
	memset(&client, 0, sizeof(client));
	client.sin_family       = AF_INET;
	
	//ipAddr = htonl(ipAddr);
	
	client.sin_port        = nTxPort;
	client.sin_addr.s_addr = ipAddr;
    while(1)
    {
		memset(revBuf, 0, sizeof(revBuf));
		nTxLen = RECV_FROM(hSocket, revBuf, sizeof(revBuf), MSG_DONTWAIT, (struct sockaddr*)&client, &socketAddrLen);
		if(nTxLen > 0)
		{
			if(g_printFn != PfSocket_Out) g_printFn = PfSocket_Out;
			
			Shell(revBuf);
		}
		
		i = 0;
		while(!QUEUE_isEmpty(&pPfSocket->m_Queue))
		{
			if(i < sizeof(revBuf))
			{
				revBuf[i++] = *((uint8*)QUEUE_getHead(&pPfSocket->m_Queue));
				QUEUE_removeHead(&pPfSocket->m_Queue);
			}
			else
			{
				nCount = 0;
				nTxLen = SEND_TO(hSocket, revBuf, i, 0 , (struct sockaddr*)&client, sizeof(client));
				while(nTxLen != i && nCount++ < MAX_PF_RESEND_COUNT)
				{
					SLEEP(1);
					nTxLen = SEND_TO(hSocket, revBuf, i, 0 , (struct sockaddr*)&client, sizeof(client));
				}
				i = 0;
			}
		}
		
		if(i)
		{
			nTxLen = SEND_TO(hSocket, revBuf, i, 0 , (struct sockaddr*)&client, sizeof(client));
			while(nTxLen != i && nCount++ < MAX_PF_RESEND_COUNT)
			{
				SLEEP(1);
				nTxLen = SEND_TO(hSocket, revBuf, i, 0 , (struct sockaddr*)&client, sizeof(client));
			}
		}
		
		SLEEP(1);
	}
}

void PfSocket_Init(const char* g_IpAddr, uint16 rxPort, uint16 txPort)
{
	memset(&g_PfSocket, 0, sizeof(g_PfSocket));
	
	g_PfSocket.m_RxPort = rxPort;
	g_PfSocket.m_TxPort = txPort;
	strcpy(g_PfSocket.m_IpAddr, g_IpAddr);
		
	QUEUE_init(&g_PfSocket.m_Queue, g_PfSocket.m_Buff, 1, sizeof(g_PfSocket.m_Buff));
}

void PfSocket_Start()
{
	uint32* pStackBuf = Null;
	int nSize = 0;
#if UCOS
	static OS_STK g_PfSocketStack[64];
	pStackBuf = (uint32*)&g_PfSocketStack;
	nSize = sizeof(g_PfSocketStack);
#endif

	CreateTask(PfSocket_task, (void *)&g_PfSocket, "PfSocket", pStackBuf, nSize);
}

int PfSocket_Out(const char* lpszFormat, ...)
{
	int i = 0;
	int nLen = 0;
	
	va_list ptr;
	va_start(ptr, lpszFormat);

	LOCK();
	
	memset(g_Pfbuffer, 0, sizeof(g_Pfbuffer));
	nLen = vsnprintfEx(g_Pfbuffer, sizeof(g_Pfbuffer), lpszFormat, ptr);
	
	va_end(ptr);

	for(i = 0; i < nLen; i++)
	{
		QUEUE_add(&g_PfSocket.m_Queue, &g_Pfbuffer[i], 1);
	}
	
	UNLOCK();

	return nLen;
}

#endif
